﻿using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.IO;

namespace Rcon
{
    /// <summary>
    /// Known Gametypes:
    /// 1;Team Deathmatch
    /// 2;Free For All
    /// 3;Capture The Flag
    /// 4;Search & Destroy
    /// 5;Headquarters
    /// 6;Domination
    /// 7;Sabotage
    /// 8;Demolition
    /// 9;Hardcore Team Deathmatch
    /// 10;Hardcore Free For All
    /// 11;Hardcore Capture The Flag
    /// 12;Hardcore Search & Destroy
    /// 13;Hardcore Headquarters
    /// 14;Hardcore Domination
    /// 15;Hardcore Sabotage
    /// 16;Hardcore Demolition
    /// 17;Barebones Team Deathmatch
    /// 18;Barebones Free For All
    /// 19;Barebones Capture The Flag
    /// 20;Barebones Search & Destroy
    /// 21;Barebones Headquarters
    /// 22;Barebones Domination
    /// 23;Barebones Sabotage
    /// 24;Barebones Demolition
    /// 25;Team Tactical
    /// 26;One in the Chamber
    /// 27;Sticks and Stones
    /// 28;Gun Game
    /// 29;Sharpshooter
    /// </summary>
    public class GametypeLookup
    {
        private Dictionary<int, string> num2Name = new Dictionary<int, string>();                           // Contains playlist number key, gametype value
        private Dictionary<string, int> name2Num = new Dictionary<string, int>();                           // Contains gametype key, playlist number value
        private Dictionary<string, List<int>> gametypeCollection = new Dictionary<string, List<int>>();     // Contains 

        public GametypeLookup()
        {
            FileInfo gametypeFile = new FileInfo("Configs\\gametypeList.cfg");
            if (gametypeFile.Exists)                  // Found the Map List Config file, load from there
            {
                string[] configStrings = File.ReadAllLines(gametypeFile.FullName);
                string[] args;
                int playListNum;
                foreach (string entry in configStrings)
                {
                    if (entry.StartsWith("//"))
                        continue;
                    args = Regex.Split(entry, ";");
                    try
                    {
                        playListNum = Convert.ToInt16(args[0]);
                    }
                    catch
                    {
                        continue;
                    }
                    num2Name.Add(playListNum, args[1]);
                }
            }
            else                                // Can't find Gametype List Config file, use Gametype defaults (Gametypes as of 9 November 2010)
            {
                num2Name.Add(1, "Team Deathmatch");
                num2Name.Add(2, "Free For All");
                num2Name.Add(3, "Capture The Flag");
                num2Name.Add(4, "Search & Destroy");
                num2Name.Add(5, "Headquarters");
                num2Name.Add(6, "Domination");
                num2Name.Add(7, "Sabotage");
                num2Name.Add(8, "Demolition");
                num2Name.Add(9, "Hardcore Team Deathmatch");
                num2Name.Add(10, "Hardcore Free For All");
                num2Name.Add(11, "Hardcore Capture The Flag");
                num2Name.Add(12, "Hardcore Search & Destroy");
                num2Name.Add(13, "Hardcore Headquarters");
                num2Name.Add(14, "Hardcore Domination");
                num2Name.Add(15, "Hardcore Sabotage");
                num2Name.Add(16, "Hardcore Demolition");
                num2Name.Add(17, "Barebones Team Deathmatch");
                num2Name.Add(18, "Barebones Free For All");
                num2Name.Add(19, "Barebones Capture The Flag");
                num2Name.Add(20, "Barebones Search & Destroy");
                num2Name.Add(21, "Barebones Headquarters");
                num2Name.Add(22, "Barebones Domination");
                num2Name.Add(23, "Barebones Sabotage");
                num2Name.Add(24, "Barebones Demolition");
                num2Name.Add(25, "Team Tactical");
                num2Name.Add(26, "One in the Chamber");
                num2Name.Add(27, "Sticks and Stones");
                num2Name.Add(28, "Gun Game");
                num2Name.Add(29, "Sharpshooter");
            }

            string gametypeName = string.Empty;
            int spaceLoc = -1;
            List<int> gametypeNums = new List<int>();
            gametypeCollection.Add("Any", new List<int>() { 0 });
            foreach (int key in num2Name.Keys)
            {
                name2Num.Add(num2Name[key], key);
                if(num2Name[key].Contains("Barebones") || num2Name[key].Contains("Hardcore"))
                {
                    spaceLoc = num2Name[key].IndexOf(" ");
                    gametypeName = num2Name[key].Substring(spaceLoc+1);
                }
                else
                    gametypeName = num2Name[key];
                if (gametypeCollection.ContainsKey(gametypeName) == false)
                    gametypeCollection.Add(gametypeName, new List<int>() { key });
                else
                {
                    gametypeNums = gametypeCollection[gametypeName];
                    gametypeNums.Add(key);
                    gametypeCollection[gametypeName] = gametypeNums;
                }
            }
        }

        /// <summary>
        /// NOT IMPLEMENTED, haven't decided on a file format
        /// </summary>
        /// <param name="playListNum"></param>
        public GametypeLookup(int playListNum)
        {
            // not implemented
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="playListName"></param>
        /// <returns>NULL if playListNum is not known</returns>
        public int GetPlayListNumber(string playListName)
        {
            if (name2Num.ContainsKey(playListName))
            {
                return name2Num[playListName];
            }
            else
            {
                return -1;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="playListNum"></param>
        /// <returns>NULL if playListName is not known</returns>
        public string GetPlayListName(int playListNum)
        {
            if (num2Name.ContainsKey(playListNum))
            {
                return num2Name[playListNum];
            }
            else
            {
                return null;
            }
        }

        public bool IsValidPlayList(string playList)
        {
            if (playList.Equals("Any"))
                return true;
            try
            {
                short num = Convert.ToInt16(playList);
                return num2Name.ContainsKey(num);
            }
            catch
            {
                return name2Num.ContainsKey(playList);
            }
        }

        public int[] GetPlayListNumbers()
        {
            int[] ia = new int[num2Name.Keys.Count];
            num2Name.Keys.CopyTo(ia, 0);
            return ia;
        }

        public string[] GetPlayListNames()
        {
            string[] sa = new string[name2Num.Keys.Count];
            name2Num.Keys.CopyTo(sa, 0);
            return sa;
        }

        public string[] GetUniquePlayListNames()
        {
            string[] sa = new string[gametypeCollection.Keys.Count];
            gametypeCollection.Keys.CopyTo(sa, 0);
            return sa;
        }

        public List<int> GetAllowablePlaylists(string key)
        {
            if (this.gametypeCollection.ContainsKey(key))
                return this.gametypeCollection[key];
            else
                return new List<int>();
        }
    }
}
